有時候會想對不同 Component 做個別樣式設定,但如果把 class 都寫在 wwwroot/css/site.css
,或是針對某個元素改動樣式,可能導致改一個就影響全部 Component,這種全域衝突是必須避免的,但應該怎麼做?
.NET 5 推出了 CSS isolation(CSS 隔離),建立 Component 個別 css 檔案,命名規範為 {Component name}.razor.css
,檔案會自動跟 {Component name}.razor
收納在一起,且名稱不分大小寫。下圖可以看到不論是 Blog.razor.css
還是 blog.razor.css
都會跟 Blog.razor
被視為同一組。
CSS isolation 會在建置時被處理,Blazor 會改寫 CSS 選擇器並產生一個 {Project name}.style.css
檔案,可以在 wwwroot/index.html (Blazor WebAssembly)
或是 Pages/_Host.cshtml (Blazor Server)
的 <head>
標籤內找到引用路徑,由於這是建置時才會產生,所以在專案內是看不到的,我們打開瀏覽器的 Dev tool 並切換到 Sources 頁籤,就能看到這檔案。
有人可能會發現為何 class 後面接著沒看過的內容,例如 .page[b-mxoy4q7bj7]
或是 .main[b-mxoy4q7bj7]
,這是 Blazor 用來辨識 CSS 選擇器作用在哪個 Component 的區域識別碼,格式為 b-10 位元數字及英文字串
,每個 Component 的區域識別碼都是獨一無二的,可知這裡的 .main
及 .page
class 只作用於 [b-mxoy4q7bj7]
對應的 Component,註解寫著 /* _content/BlazorServer/Shared/MainLayout.razor.rz.scp.css */
,打開 Shared/MainLayout.razor.css
,的確看到了 .main
及 .page
class,rz.scp.css
附檔名是用來辨識 CSS 選擇器屬於哪個 Component。
我們在 Blog.razor.css
加上一段針對 label 的樣式修改,按下 ctrl + shift + B
建置專案,再看網頁就能看到文字顏色改變了,BlazorServer.style.css
也能看到 Blog.razor.rz.scp.css
的樣式區塊多了一段 label[b-0ae5hiw99t]
。
label {
color: darkcyan
}
如果想對 Post Component 的 label 元素套用相同樣式,又不想分別建立 razor.css 檔案呢?Blazor 提供了方便的做法,只要在 CSS 選擇器前面加上 ::deep
即可,我們在 Blog.razor.css
的 label 前面加上 ::deep
,就能看到 Post 的 label 元素顏色都改變了,BlazorServer.style.css
的 class 也從 label[b-0ae5hiw99t]
變成了 [b-0ae5hiw99t] label
。
不過要注意的是,必須有父子關係 ::deep
才能生效,Parent Compoent 的區域識別碼僅作用於 <div>
標籤,如果 Child Component 沒有被 <div>
標籤包住就不會生效。我們把 Blog.razor
中包住 Post Component 的 <div>
標籤都註解,儲存後再去網頁看,發現 <label>
文字顏色都變回黑色了,但 BlazorServer.style.css
的 class 仍舊是 [b-0ae5hiw99t] label
。
Ref: ASP.NET Core Blazor CSS isolation